/// ------------------------------------------------------------------------------------------------------------------------------------
///
/// MIT License
///
/// Permission is hereby granted, free of charge, to any person obtaining a copy
/// of this software and associated documentation files (the "Software"), to deal
/// in the Software without restriction, including without limitation the rights
/// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
/// copies of the Software, and to permit persons to whom the Software is
/// furnished to do so, subject to the following conditions:
///
/// The above copyright notice and this permission notice shall be included in all
/// copies or substantial portions of the Software.
///
/// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
/// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
/// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
/// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
/// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
/// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
/// SOFTWARE.
///
/// Copyright (c) 2024 ycz. All rights reserved.
///
/// Created by ycz on 24-11-7.
///
/// @file  app_cli.c
///
/// @brief
///     应用层 命令行 实现
///
/// ------------------------------------------------------------------------------------------------------------------------------------



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 头文件
/// ------------------------------------------------------------------------------------------------------------------------------------

#include "app_cli.h"

#include <string.h>
#include <stdlib.h>
#include "y_sa.h"



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 枚举
/// ------------------------------------------------------------------------------------------------------------------------------------

/// 命令枚举 命令行字符串 要与下面命令字符串一一对应
typedef enum {
    CLI_NONE,     ///< 空
    CLI_GET_MAC,  ///< 获取 MAC
    CLI_REBOOT,   ///< 重启本机 或指定 mac 的设备
    CLI_RESET,    ///< 重置本机 或指定 mac 的设备
    CLI_SET_NUM,  ///< 设置本机设备编号
    CLI_GET_NUM,  ///< 获取本机设备编号
    CLI_HELP,     ///< 帮助
} CLI_CMD_e;



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 全局变量
/// ------------------------------------------------------------------------------------------------------------------------------------

static uint8_t g_cmd_str[][24] = {
        "NONE",
        "get_mac",
        "reboot",
        "reset",
        "set_num",
        "get_num",
        "help",
};  ///< 命令行字符串 命令有相同的字段时 长一点的放前面 如 get_mac 与 get_mac_list，get_mac_list需放在前面



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 私有函数
/// ------------------------------------------------------------------------------------------------------------------------------------

/// @brief   获取命令类型
/// @param   [in] data                     数据指针
static CLI_CMD_e _app_cli_get_cmd(uint8_t *data) {

    if (data) {
        for (int i = 0; i < sizeof(g_cmd_str) / sizeof(g_cmd_str[0]); ++i) {
            if (strstr((char *) data, (char *) g_cmd_str[i])) {
                return i;
            }
        }
    }
    return 0;
}

/// @brief   命令行数据处理
/// @param   [in] data                     命令行数据
/// @param   [in] size                     命令行数据大小
static void _app_cli_handle(uint8_t *data, uint16_t size) {

    // 断言
    YLOGA(data);
    YLOGA(size);

    // 命令分类处理
    uint8_t  *p      = (uint8_t *) strtok((char *) data, " ");  // 字符串分割
    CLI_CMD_e cmd_id = _app_cli_get_cmd(p);
    while (strlen((char *) p) != 0 && cmd_id == 0) {
        p      = (uint8_t *) strtok(NULL, " ");
        cmd_id = _app_cli_get_cmd(p);
    }

    printf("\r\n");
    switch (cmd_id) {

        case CLI_GET_MAC:
            printf("get_mac " MAC_FORMAT "FFFF ok! \r\n\r\n", MAC_TO_STR(y_sys_get_mac()));
            break;

        case CLI_REBOOT: {
            printf("reboot ok \r\n\r\n");
            y_ll_reboot();
        } break;

        case CLI_RESET: {
            printf("reset ok \r\n\r\n");
            y_time_set_timestamp(0);  // 时间恢复默认
            y_nvs_reset();            // 参数恢复默认设置
            y_ll_reboot();
        } break;

        case CLI_SET_NUM: {
            uint8_t dev_num = strtol(strtok(NULL, " "), NULL, 10);
            printf("set_num  %d  %s!\r\n\r\n", dev_num, y_sys_set_dev_num(dev_num) ? "ok" : "fail");
        } break;

        case CLI_GET_NUM: {
            printf("get_num  %d  ok!\r\n\r\n", y_sys_get_dev_num());
        } break;

        case CLI_HELP: {
            printf("        get_mac                                         获取本机 mac \r\n");
            printf("        reboot                                          重启本机 \r\n");
            printf("        reset                                           重置本机 \r\n");
            printf("        set_num                                         设置本机编号 \r\n");
            printf("        get_num                                         获取本机编号 \r\n");
            printf("        help                                            帮助 \r\n\r\n");
        } break;
    }
    printf("[root]# ");  // 打印命令行 标志
    fflush(stdout);
}



/// ------------------------------------------------------------------------------------------------------------------------------------
/// 公有函数
/// ------------------------------------------------------------------------------------------------------------------------------------

/// @brief   打印 app_cli 版本信息
void app_cli_print_version() {
    YLOG_VERSION("app_cli", APP_CLI_MAJOR, APP_CLI_MINOR, APP_CLI_PATCH);
}

/// @brief   初始化
/// @retval  true                          成功
/// @retval  false                         失败
bool app_cli_init() {

    // 命令行任务初始化
    y_cli_init();
    CLI_CONFIG_st *conig = y_cli_config_get();
    conig->is_open       = true;
    conig->is_fflush     = true;
    conig->open_time_s   = 0;
    conig->cli_cb        = _app_cli_handle;
    YLOGA_FALSE(y_cli_config_set(conig));
    y_cli_config_print(conig);

    return true;
}

/// @brief   任务处理
/// @param   [in] time_ms                  每次调用间隔时间
void app_cli_process(uint32_t time_ms) {
    y_cli_process(time_ms);  // 命令行处理
}